package org.hospital.entity;

// default package

import java.sql.Date;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;

import static org.hibernate.criterion.Example.create;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.annotation.Transactional;

/**
 * A data access object (DAO) providing persistence and search support for
 * Employee entities. Transaction control of the save(), update() and delete()
 * operations can directly support Spring container-managed transactions or they
 * can be augmented to handle user-managed Spring transactions. Each of these
 * methods provides additional information for how to configure it for the
 * desired type of transaction control.
 * 
 * @see .Employee
 * @author MyEclipse Persistence Tools
 */
@Transactional
public class EmployeeDAO {
	private static final Logger log = LoggerFactory.getLogger(EmployeeDAO.class);
	// property constants
	public static final String POSITION_ID = "positionId";
	public static final String DEPARTMENT_ID = "departmentId";
	public static final String CLINIC_ID = "clinicId";
	public static final String EMPLOYEE_CODE = "employeeCode";
	public static final String ACCOUNT = "account";
	public static final String PWD = "pwd";
	public static final String NAME = "name";
	public static final String AGE = "age";
	public static final String SEX = "sex";
	public static final String LOGIN_IP = "loginIp";
	public static final String STATUS = "status";
	public static final String IS_ON_JOB = "isOnJob";
	public static final String IS_DOMAIN = "isDomain";

	private SessionFactory sessionFactory;

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	private Session getCurrentSession() {
		return sessionFactory.getCurrentSession();
	}

	protected void initDao() {
		// do nothing
	}
	
	public List<Employee> getByProperties(Map properties) {
		Criteria c = getCurrentSession().createCriteria(Employee.class);
		c.add(Restrictions.allEq(properties));
		c.list();
		return c.list();
	}
	
	/**
	 * 获取门诊负责人候选人
	 * @param clinicId
	 * @return
	 */
	public List<Employee> getClinicPrincipal() {
		log.debug("getClinicPrincipal");
		try {
			StringBuilder hql = new StringBuilder();
			hql.append("SELECT e ");
			hql.append("FROM Employee as e,Position as p ");
			hql.append("WHERE e.positionId = p.positionId ");
			hql.append("AND p.rank >= 3 ");
			hql.append("AND e.isOnJob = 0");
			Query q = getCurrentSession().createQuery(hql.toString());
			List<Employee> eList = q.list();
			log.debug("getClinicPrincipal successful");
			return eList;
		} catch (RuntimeException re) {
			log.error("getClinicPrincipal failed", re);
			throw re;
		}
	}
	
	/**
	 * 获取科室负责人候选人
	 * @param departmentId
	 * @return
	 */
	public List<Employee> getDepartmentPrincipal(int clinicId) {
		log.debug("getClinicPrincipal");
		try {
			StringBuilder hql = new StringBuilder();
			hql.append("SELECT e ");
			hql.append("FROM Employee as e,Position as p ");
			hql.append("WHERE e.positionId = p.positionId ");
			hql.append("AND p.rank >= 2 ");
			hql.append("AND e.clinicId >= :clinicId ");
			hql.append("AND e.isOnJob = 0");
			Query q = getCurrentSession().createQuery(hql.toString());
			q.setParameter("clinicId", clinicId);
			List<Employee> eList = q.list();
			log.debug("getClinicPrincipal successful");
			return eList;
		} catch (RuntimeException re) {
			log.error("getClinicPrincipal failed", re);
			throw re;
		}
	}
	/**
	 * 获取employee数据
	 */
	public List<Employee> getEmployeeData(int clinicId,int pageIndex,int pageSize){
		try{
			String hql = "SELECT e FROM Employee as e WHERE e.clinicId = :clinicId order by e.employeeId";
			Query q=getCurrentSession().createQuery(hql);
			q.setFirstResult((pageIndex-1)*pageSize);
			q.setMaxResults(pageSize);
			
			//System.out.println("getEmployeeData.setFirstResult : " + ((pageIndex-1)*pageSize));
			//System.out.println("getEmployeeData.setMaxResults : "+(pageSize));
			q.setParameter("clinicId", clinicId);
			List<Employee> eList=q.list();
			return eList;
		}catch (RuntimeException re) {
			log.error("getClinicPrincipal failed", re);
			throw re;
		}
	}
	
	public Long getClinicEmployeeNumber(int clinicId) {
		try{
			String hql = "SELECT count(e.employeeId) FROM Employee as e WHERE e.clinicId = :clinicId";
			Query q=getCurrentSession().createQuery(hql);
			q.setParameter("clinicId", clinicId);
			
			return ((Number)q.uniqueResult()).longValue();
		}catch (RuntimeException re) {
			log.error("getClinicPrincipal failed", re);
			throw re;
		}
	}
	
	/**
	 * 根据search检索获取employee数据
	 */
	public List<Employee> getSearchEmployeeData(int clinicId,String search){
		try{
			StringBuilder hql= new StringBuilder();
			hql.append("SELECT e FROM Employee as e ");
			hql.append("WHERE e.clinicId = :clinicId ");
			hql.append("and ");
			hql.append("e.name LIKE '%"+search+"%' ");
			hql.append("or ");
			hql.append("e.employeeCode LIKE '%"+search+"%' ");
			Query q=getCurrentSession().createQuery(hql.toString());
			q.setParameter("clinicId", clinicId);
			
			List<Employee> eList=q.list();
			return eList;
		}catch (RuntimeException re) {
			log.error("getClinicPrincipal failed", re);
			throw re;
		}
	}
	/**
	 * 获取门诊在[startTime,endTime]开过某治疗项目的所有(科室、门诊)医生
	 * @param Id id stauts=0 表示部门id   status = 1 表示门诊id
	 * @param projectId
	 * @param startTime
	 * @param endTime
	 * @param status  0：查询部门内的；1：查询门诊内的
	 * @return
	 */
	public List<Employee> getTreatmentDoctor(int Id,int projectId,long startTime,long endTime,int status) {
		log.debug("getTreatmentClinicDoctor instance");
		if(status != 1 && status != 0) {
			return null;
		}
		try {
			String hql = "";
			if(status == 1) {
				hql = "SELECT DISTINCT e "
					+ "FROM Employee as e,Bill as b,BillProject as bp "
					+ "WHERE e.employeeId = b.doctorId "
					+ "AND bp.id.billId = b.billId "
					+ "AND b.status = 0 "
					+ "AND b.category = 'treatmentBill' "
					+ "AND b.clinicId = :Id " //改变地方
					+ "AND bp.id.projectId = :projectId "
					+ "AND b.datetime >= :startTime "
					+ "AND b.datetime <= :endTime";
			}
			if(status == 0) {
				hql = "SELECT DISTINCT e "
					+ "FROM Employee as e,Bill as b,BillProject as bp "
					+ "WHERE e.employeeId = b.doctorId "
					+ "AND bp.id.billId = b.billId "
					+ "AND b.status = 0 "
					+ "AND b.category = 'treatmentBill' "
					+ "AND b.departmentId = :Id "
					+ "AND bp.id.projectId = :projectId "
					+ "AND b.datetime >= :startTime "
					+ "AND b.datetime <= :endTime";
			}
			Query q = getCurrentSession().createQuery(hql);
			q.setParameter("Id", Id);
			q.setParameter("projectId", projectId);
			q.setParameter("startTime", new Date(startTime));
			q.setParameter("endTime", new Date(endTime));
			List<Employee> result = q.list();
			log.debug("getTreatmentDoctor successful");
			return result;
		} catch (RuntimeException re) {
			log.error("getTreatmentDoctor failed", re);
			throw re;
		}
	}
	
	/**
	 * 查询在[startTime,endTime]执行过某治疗项目的所有(本门诊、本部门)执行者
	 * @param id 表示部门id(status=0) 表示门诊id(status=1)
	 * @param projectId
	 * @param startTime
	 * @param endTime
	 * @param status  0：查询部门内的；1：查询门诊内的
	 * @return
	 */
	public List<Employee> getTreatmentExcutor(int id,int projectId,long startTime,long endTime,int status) {
		log.debug("getTreatmentExcutor instance");
		if(status != 1 && status != 0) {
			return null;
		}
		try {
			String hql = "";
			if(status == 1) {
				hql = "SELECT DISTINCT e "
					+ "FROM Employee as e,TreatInfo as ti,MedicalCard as mc "
					+ "WHERE ti.excutorId = e.employeeId "
					+ "AND ti.medicalCardId = mc.medicalCardId "
					+ "AND mc.projectId = :projectId "
					+ "AND ti.clinicId = :id "   //改变的地方
					+ "AND ti.treatTime >= :startTime "
					+ "AND ti.treatTime <= :endTime";
			}
			if(status == 0) {
				hql = "SELECT DISTINCT e "
					+ "FROM Employee as e,TreatInfo as ti,MedicalCard as mc "
					+ "WHERE ti.excutorId = e.employeeId "
					+ "AND ti.medicalCardId = mc.medicalCardId "
					+ "AND mc.projectId = :projectId "
					+ "AND ti.departmentId = :id "
					+ "AND ti.treatTime >= :startTime "
					+ "AND ti.treatTime <= :endTime";
			}
			
			Query q = getCurrentSession().createQuery(hql);
			q.setParameter("id", id);
			q.setParameter("projectId", projectId);
			q.setParameter("startTime", new Date(startTime));
			q.setParameter("endTime", new Date(endTime));
			List<Employee> result = q.list();
			log.debug("getTreatmentExcutor successful");
			return result;
		} catch (RuntimeException re) {
			log.error("getTreatmentExcutor failed", re);
			throw re;
		}
	}
	
	/**
	 * 获取在[startTime,endTime]本院开的单分院执行者执行的治疗记录
	 * 如果status=1 则departmentId参数没有用处；
	 * @param clinicId
	 * @param departmentId
	 * @param projectId
	 * @param startTime
	 * @param endTime
	 * @param status  0：查询本门诊其他部门内的；1：查询其他门诊内的(其他门诊其他部门的)
	 * @return
	 */
	public List<Employee> getTreatmentOtherExcutor(int clinicId,int departmentId,int projectId,long startTime,long endTime,int status) {
		log.debug("getTreatmentOtherExcutor instance");
		if(status != 1 && status != 0) {
			return null;
		}
		try {
			String hql = "";
			List<Employee> result = new ArrayList<Employee>();
			if(status == 1) {
				hql = "SELECT DISTINCT e "
					+ "FROM Employee as e,TreatInfo as ti,MedicalCard as mc,Bill as b "
					+ "WHERE ti.excutorId = e.employeeId "
					+ "AND ti.medicalCardId = mc.medicalCardId "
					+ "AND mc.billId = b.billId "
					+ "AND b.clinicId = :clinicId "
					+ "AND b.status = 0 "
					+ "AND mc.projectId = :projectId "
					+ "AND ti.clinicId != :clinicId "  //表示其他门诊;或者其他门诊的其他部门
					+ "AND ti.treatTime >= :startTime "
					+ "AND ti.treatTime <= :endTime";
				
				Query q = getCurrentSession().createQuery(hql);
				q.setParameter("clinicId", clinicId);
				q.setParameter("projectId", projectId);
				q.setParameter("startTime", new Date(startTime));
				q.setParameter("endTime", new Date(endTime));
				result = q.list();
				log.debug("getTreatmentOtherExcutor successful");
			}
			if(status == 0) {
				hql = "SELECT DISTINCT e "
					+ "FROM Employee as e,TreatInfo as ti,MedicalCard as mc,Bill as b "
					+ "WHERE ti.excutorId = e.employeeId "
					+ "AND ti.medicalCardId = mc.medicalCardId "
					+ "AND mc.billId = b.billId "
					+ "AND b.status = 0 "
					+ "AND b.departmentId = :departmentId "
					+ "AND mc.projectId = :projectId "
					+ "AND ti.clinicId = :clinicId "  //表示本门诊的其他部门
					+ "AND ti.departmentId != :departmentId "
					+ "AND ti.treatTime >= :startTime "
					+ "AND ti.treatTime <= :endTime";
				
				Query q = getCurrentSession().createQuery(hql);
				q.setParameter("clinicId", clinicId);
				q.setParameter("departmentId", departmentId);
				q.setParameter("projectId", projectId);
				q.setParameter("startTime", new Date(startTime));
				q.setParameter("endTime", new Date(endTime));
				result = q.list();
				log.debug("getTreatmentOtherExcutor successful");
			}
			
			return result;
		} catch (RuntimeException re) {
			log.error("getTreatmentOtherExcutor failed", re);
			throw re;
		}
	}
	
	/**
	 * 验证登陆
	 * @param account
	 * @param pwd
	 * @return
	 */
	public Employee getByAccountAndPwd(String account, String pwd) {
		Criteria c = getCurrentSession().createCriteria(Employee.class);
		c.add(Restrictions.eq("account", account));
		c.add(Restrictions.eq("pwd", pwd));
		c.add(Restrictions.eq("isOnJob", 0));
		List result = c.list();

		if (result == null || result.size() == 0) {
			return null;
		}

		Employee e = (Employee) result.get(0);
		return e;
	}

	public void save(Employee transientInstance) {
		log.debug("saving Employee instance");
		try {
			getCurrentSession().save(transientInstance);
			log.debug("save successful");
		} catch (RuntimeException re) {
			log.error("save failed", re);
			throw re;
		}
	}

	public void delete(Employee persistentInstance) {
		log.debug("deleting Employee instance");
		try {
			getCurrentSession().delete(persistentInstance);
			log.debug("delete successful");
		} catch (RuntimeException re) {
			log.error("delete failed", re);
			throw re;
		}
	}

	public Employee findById(java.lang.Integer id) {
		log.debug("getting Employee instance with id: " + id);
		try {
			Employee instance = (Employee) getCurrentSession().get("org.hospital.entity.Employee", id);
			return instance;
		} catch (RuntimeException re) {
			log.error("get failed", re);
			throw re;
		}
	}

	public List<Employee> findByExample(Employee instance) {
		log.debug("finding Employee instance by example");
		try {
			List<Employee> results = (List<Employee>) getCurrentSession()
					.createCriteria("Employee").add(create(instance)).list();
			log.debug("find by example successful, result size: " + results.size());
			return results;
		} catch (RuntimeException re) {
			log.error("find by example failed", re);
			throw re;
		}
	}

	public List findByProperty(String propertyName, Object value) {
		log.debug("finding Employee instance with property: " + propertyName + ", value: " + value);
		try {
			String queryString = "from Employee as model where model." + propertyName + "= ?";
			Query queryObject = getCurrentSession().createQuery(queryString);
			queryObject.setParameter(0, value);
			return queryObject.list();
		} catch (RuntimeException re) {
			log.error("find by property name failed", re);
			throw re;
		}
	}

	public List<Employee> findByPositionId(Object positionId) {
		return findByProperty(POSITION_ID, positionId);
	}

	public List<Employee> findByDepartmentId(Object departmentId) {
		return findByProperty(DEPARTMENT_ID, departmentId);
	}

	public List<Employee> findByClinicId(Object clinicId) {
		return findByProperty(CLINIC_ID, clinicId);
	}

	public List<Employee> findByEmployeeCode(Object employeeCode) {
		return findByProperty(EMPLOYEE_CODE, employeeCode);
	}

	public List<Employee> findByAccount(Object account) {
		return findByProperty(ACCOUNT, account);
	}

	public List<Employee> findByPwd(Object pwd) {
		return findByProperty(PWD, pwd);
	}

	public List<Employee> findByName(Object name) {
		return findByProperty(NAME, name);
	}

	public List<Employee> findByAge(Object age) {
		return findByProperty(AGE, age);
	}

	public List<Employee> findBySex(Object sex) {
		return findByProperty(SEX, sex);
	}

	public List<Employee> findByLoginIp(Object loginIp) {
		return findByProperty(LOGIN_IP, loginIp);
	}

	public List<Employee> findByStatus(Object status) {
		return findByProperty(STATUS, status);
	}

	public List<Employee> findByIsOnJob(Object isOnJob) {
		return findByProperty(IS_ON_JOB, isOnJob);
	}

	public List<Employee> findByIsDomain(Object isDomain) {
		return findByProperty(IS_DOMAIN, isDomain);
	}

	public List findAll() {
		log.debug("finding all Employee instances");
		try {
			String queryString = "from Employee";
			Query queryObject = getCurrentSession().createQuery(queryString);
			return queryObject.list();
		} catch (RuntimeException re) {
			log.error("find all failed", re);
			throw re;
		}
	}

	public Employee merge(Employee detachedInstance) {
		log.debug("merging Employee instance");
		try {
			Employee result = (Employee) getCurrentSession().merge(detachedInstance);
			log.debug("merge successful");
			return result;
		} catch (RuntimeException re) {
			log.error("merge failed", re);
			throw re;
		}
	}

	public void attachDirty(Employee instance) {
		log.debug("attaching dirty Employee instance");
		try {
			getCurrentSession().saveOrUpdate(instance);
			log.debug("attach successful");
		} catch (RuntimeException re) {
			log.error("attach failed", re);
			throw re;
		}
	}

	public void attachClean(Employee instance) {
		log.debug("attaching clean Employee instance");
		try {
			getCurrentSession().buildLockRequest(LockOptions.NONE).lock(instance);
			log.debug("attach successful");
		} catch (RuntimeException re) {
			log.error("attach failed", re);
			throw re;
		}
	}

	public static EmployeeDAO getFromApplicationContext(ApplicationContext ctx) {
		return (EmployeeDAO) ctx.getBean("EmployeeDAO");
	}
}